package expressions;

import values.Value;
import values.Integer;
import values.Array;
import base.AST;
import base.Environment;
import base.Identifier;
import base.Interpreter;

public class ArrayAccess implements Expression {

	private Identifier identifier;
	private AST index;

	/**
	 * Creates an expression that represents an access to variable number
	 * 'index' in array identified by 'identifier'
	 * 
	 * @param identifier
	 *            the array's identifier
	 * @param index
	 *            a Value or an Integer
	 */

	public ArrayAccess(Identifier identifier, AST index) {
		assert index instanceof Expression || index instanceof Integer;

		this.identifier = identifier;
		this.index = index;
	}

	/**
	 * Returns identifier[eval(index)] if identifier refers to an Array and
	 * eval(index) is an integer. Throws a BadExpressionValueException
	 * otherwise.
	 */

	public Value eval(Environment env) throws BadExpressionException {
		assert env.contains(this.identifier);

		Integer intIndex = Interpreter.getInt(this.index, env);

		if (intIndex != null) {
			Value array = env.getValue(identifier);

			if (array instanceof Array)
				return ((Array) array).eval(intIndex.eval());
			else
				throw new BadExpressionException(
						"Trying to access an Array that is not an Array");
		} else
			throw new BadExpressionException(
					"Trying to access an Array with a non-integer index");

	}

}
